package de.justphil.tcg.tcgserver.rest.validators;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.core.Response;


import de.justphil.tcg.tcgserver.commons.config.RestConfig;
import de.justphil.tcg.tcgserver.commons.domain.User;
import de.justphil.tcg.tcgserver.commons.domain.wrappers.CreateDeck;
import de.justphil.tcg.tcgserver.commons.exceptions.TCGException;
import de.justphil.tcg.tcgserver.commons.i18n.Error;
import de.justphil.tcg.tcgserver.commons.management.DataManager;
import de.justphil.tcg.tcgserver.commons.util.StringUtil;

public class DeckValidator {

	public void validatePost(DataManager dataManager, User user, CreateDeck createDeck) throws TCGException {
		
		validateCreateDeckObject(createDeck);
		
		validateName(createDeck.getName());
		
		validateOccurrences(createDeck.getCardInstances());
		
		validateCardInstanceOwnership(dataManager, user, createDeck.getCardInstances());
		
		validateMultiplicity(createDeck.getCardInstances());
		
	}
	
	public void validateDelete(DataManager dataManager, User user, long deckId) throws TCGException {
		
		validateOwnership(dataManager, user, deckId);
		
		validateMinOneOtherDeckAvail(user);
		
	}
	
	
	
	/* ######################################################################## */
	/* ######################################################################## */
	/* ######################################################################## */
	
	private void validateCreateDeckObject(CreateDeck createDeck) throws TCGException {
		
		if (createDeck == null || createDeck.getCardInstances() == null) {
			throw new TCGException(Error.CLIENT_ERROR_INVALID_DECK_DATA, Response.Status.BAD_REQUEST);
		}
		
	}
	
	private void validateName(String name) throws TCGException {
		
		if (StringUtil.isNullOrEmpty(name)) {
			throw new TCGException(Error.CLIENT_ERROR_INVALID_DECK_NAME, Response.Status.BAD_REQUEST);
		}
		
		if (name.length() < RestConfig.DECK_NAME_MIN_CHARS) {
			throw new TCGException(Error.CLIENT_ERROR_DECK_NAME_LESS_THAN_MIN, Response.Status.BAD_REQUEST);
		}
		
		if (name.length() > RestConfig.DECK_NAME_MAX_CHARS) {
			throw new TCGException(Error.CLIENT_ERROR_DECK_NAME_GREATER_THAN_MAX, Response.Status.BAD_REQUEST);
		}
		
	}
	
	private void validateOccurrences(long[] cardInstances) throws TCGException {
		
		if (cardInstances.length < RestConfig.DECK_MIN_CIS) {
			throw new TCGException(Error.CLIENT_ERROR_DECK_CIS_LESS_THAN_MIN, Response.Status.BAD_REQUEST);
		}
		
		if (cardInstances.length > RestConfig.DECK_MAX_CIS) {
			throw new TCGException(Error.CLIENT_ERROR_DECK_CIS_GREATER_THAN_MAX, Response.Status.BAD_REQUEST);
		}
		
	}
	
	private void validateCardInstanceOwnership(DataManager dataManager, User user, long[] cardInstances) throws TCGException {
		
		for (int i = 0; i < cardInstances.length; i++) {
			if ( !user.getCardInstances().contains( dataManager.getCardInstanceById( cardInstances[i] ) ) ) {
				throw new TCGException(Error.CLIENT_ERROR_NOT_CARD_INSTANCE_OWNER, Response.Status.FORBIDDEN);
			}
		}
		
	}
	
	private void validateOwnership(DataManager dataManager, User user, long deckId) throws TCGException {
		
		if (!user.getDecks().contains( dataManager.getDeckById( deckId ) )) {
			throw new TCGException(Error.CLIENT_ERROR_NOT_DECK_OWNER, Response.Status.FORBIDDEN);
		}
		
	}
	
	private void validateMultiplicity(long[] cardInstances) throws TCGException {
		
		Set<Long> in = new HashSet<Long>(cardInstances.length);
		
		for (int i = 0; i < cardInstances.length; i++) {
			if (in.contains( cardInstances[i] )) {
				throw new TCGException(Error.CLIENT_ERROR_INVALID_CI_MULTIPLICITY, Response.Status.BAD_REQUEST);
			}
			
			in.add( cardInstances[i] );
		}
		
	}
	
	private void validateMinOneOtherDeckAvail(User user) throws TCGException {
		
		if (user.getDecks().size() < 2) {
			throw new TCGException(Error.CLIENT_ERROR_MIN_ONE_DECK_REQUIRED, Response.Status.BAD_REQUEST);
		}
		
	}
	
}
